package com.boarsoft.boar.oss.util;


import com.boarsoft.bean.ReplyInfo;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/**
 * @author tao.wang57
 * @desc 上传对象工具类<p>
 * <p>
 * 流式上传<br>
 * 文件上传<br>
 * 分段上传<br> no
 * 追加上传<br> no
 * 断点续传上传<br> no
 * 基于表单上传<br> no
 * @date 2023-03-25 am
 */
public class UploadObjectUtil {

    private static final Logger log = LoggerFactory.getLogger(UploadObjectUtil.class);

    /**
     * 流式上传 - 上传文件流
     *
     * @param obsClient  obs客户端
     * @param bucketName 桶名称
     * @param localFile  待上传的本地文件路径，需要指定到具体的文件名
     * @param objectKey  对象名，对象名是对象在存储桶中的唯一标识。对象名是对象在桶中的完整路径，路径中不包含桶名。
     *                   例如，您对象的访问地址为 examplebucket.obs.cn-north-4.myhuaweicloud.com/folder/test.txt 中，
     *                   对象名为folder/test.txt。长度大于0且不超过1024的字符串。
     * @return
     */
    public static ReplyInfo<Object> uploadStream(ObsClient obsClient, String bucketName, String localFile, String objectKey) {
        try {
            // 待上传的本地文件路径，需要指定到具体的文件名
            FileInputStream fis = new FileInputStream(new File(localFile));
            obsClient.putObject(bucketName, objectKey, fis);
            // 待上传的本地文件路径，需要指定到具体的文件名（方式二）
            /*FileInputStream fis2 = new FileInputStream(new File(localFile));
            PutObjectRequest request = new PutObjectRequest();
            request.setBucketName(bucketName);
            request.setObjectKey(objectKey);
            request.setInput(fis2);
            obsClient.putObject(request);*/
            log.info("putObject successfully");
        } catch (ObsException e) {
            log.error("putObject failed ObsException:", e);
            printObsException(e);
        } catch (Exception e) {
            // 其他异常信息打印
            log.error("putObject failed", e);
        } finally {
            closeClient(obsClient);
        }
        return ReplyInfo.SUCCESS;
    }


    public static ReplyInfo<Object> uploadStream(InputStream input, ObsClient obsClient, String bucketName, String objectKey) {
        try {
            obsClient.putObject(bucketName, objectKey, input);
            log.info("putObject successfully");
        } catch (ObsException e) {
            log.error("putObject failed ObsException:", e);
            printObsException(e);
        } catch (Exception e) {
            // 其他异常信息打印
            log.error("putObject failed", e);
        } finally {
            closeClient(obsClient);
        }
        return ReplyInfo.SUCCESS;
    }

    /**
     * 流式上传 - 上传字符串（byte数组）
     *
     * @param obsClient
     * @param content    上传字符串（byte数组）
     * @param bucketName
     * @param objectKey  对象名
     * @return
     */
    public static ReplyInfo<Object> uploadString(ObsClient obsClient, String content, String bucketName, String objectKey) {
        try {
            obsClient.putObject(bucketName, objectKey, new ByteArrayInputStream(content.getBytes()));
            log.info("putObject successfully");
        } catch (ObsException e) {
            log.error("putObject failed ObsException:", e);
            printObsException(e);
        } catch (Exception e) {
            // 其他异常信息打印
            log.error("putObject failed", e);
        } finally {
            closeClient(obsClient);
        }
        return ReplyInfo.SUCCESS;
    }

    /**
     * 文件上传
     *
     * @param obsClient
     * @param bucketName
     * @param objectKey
     * @param localFile  为待上传的本地文件路径，需要指定到具体的文件名
     * @return
     */
    public static ReplyInfo<Object> uploadFile(ObsClient obsClient, String bucketName, String objectKey, String localFile) {
        try {
            // 文件上传
            // localfile为待上传的本地文件路径，需要指定到具体的文件名
            obsClient.putObject(bucketName, objectKey, new File(localFile));
            // localfile2 为待上传的本地文件路径，需要指定到具体的文件名
            /*PutObjectRequest request = new PutObjectRequest();
            request.setBucketName("examplebucket");
            request.setObjectKey("objectkey2");
            request.setFile(new File("localfile2"));
            obsClient.putObject(request);*/
            log.info("putObject successfully");
        } catch (ObsException e) {
            log.error("putObject failed", e);
            printObsException(e);
        } catch (Exception e) {
            // 其他异常信息打印
            log.error("putObject failed", e);
        } finally {
            closeClient(obsClient);
        }
        return ReplyInfo.SUCCESS;
    }

    private static void closeClient(ObsClient obsClient) {
        if (obsClient != null) {
            try {
                obsClient.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static void printObsException(ObsException e) {
        // 请求失败,打印http状态码
        log.error("HTTP Code:" + e.getResponseCode());
        // 请求失败,打印服务端错误码
        log.error("Error Code:" + e.getErrorCode());
        // 请求失败,打印详细错误信息
        log.error("Error Message:" + e.getErrorMessage());
        // 请求失败,打印请求id
        log.error("Request ID:" + e.getErrorRequestId());
        log.error("Host ID:" + e.getErrorHostId());
    }
}
